package streamforce.crypto.owner;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.espertech.esper.client.EPServiceProvider;

import streamforce.crypto.KPAbe;
import streamforce.crypto.event.StockEvent;
//sending events
public class EPOwner {
	EPServiceProvider epService; 
	KPAbe cryptoHandler;
	int streamId;
	byte[] pK; 
	int[] windowSizes = null;
	DataEncryptor encryptor; 
	int aggregateType; //1,2,3
	public EPOwner(int ownerId, EPServiceProvider ep){
		this.epService = ep; 
		this.streamId = ownerId;
		this.initialization();		
		encryptor = new DataEncryptor(this.streamId, this.cryptoHandler, this.windowSizes);
	}
	
	public KPAbe getCryptoHandler(){
		return this.cryptoHandler;
	}
	
	//initializing crypto
	private void initialization(){
		Properties prop = new Properties();
		try {
			prop.load(new FileInputStream("attributes.properties"));			
			int nAttributes = new Integer(prop.getProperty("nStocks")).intValue();
			String[] ws = prop.getProperty("windowSizes").split(",");
			String[] universe = new String[nAttributes+5+(ws.length)];
			int i=0;
			for (i=0; i<nAttributes; i++){
				universe[i] = "stockId_"+i;			
			}
			universe[i] = "timestamp = ";i++;
			universe[i] = "ws_x";i++;//all window sizes > 1
			universe[i] = "ws_1";i++;
			universe[i] = "att_price";i++;
			universe[i] = "att_volume";i++;
						
			windowSizes = new int[ws.length];
			for (int j=0; j<ws.length; j++){
				windowSizes[j] = new Integer(ws[j]).intValue();
				universe[i+j] = "ws_"+windowSizes[j];
				//System.out.println("Window size = "+windowSizes[j]);
			}						
			
			cryptoHandler = new KPAbe();
			this.pK = cryptoHandler.initOwner(this.streamId, universe, 2, windowSizes);			
			if (prop.containsKey("aggregateType") && !prop.getProperty("aggregateType").isEmpty())
				this.aggregateType = new Integer(prop.getProperty("aggregateType")).intValue();
			else
				this.aggregateType = -1;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public byte[] getPK(){
		return this.pK;
	}
	
	public byte[] generateUserWindowKey(int windowSize){
		return this.cryptoHandler.generateUserWindowKey_Aggregate1(this.streamId, windowSize);
	}
	
	public byte[] generateTransformKey(String policy, int userId){
		return this.cryptoHandler.generateTransformKey(this.streamId, policy, userId);
	}
	
	public byte[] generateUserDecKey(int userId){
		return this.cryptoHandler.generateUserDecryptionKey(this.streamId, userId);
	}
	
	public byte[] generateUserDetKey(int userId){
		return this.cryptoHandler.generateUserDetKey(this.streamId);
	}
	
	public void sendEvents(){		
		int n = 4;
		int ts = 0;
		int price = 0;
		int volume = 50;
		StockEvent sd=null, sd1=null;							
		for (int i = 0; i < n; i++) {
			//sd = new StockEvent();
			//sd.initialization(this.cryptoHandler, i+ts, 0, price+i+1, volume+i, this.windowSizes);
			switch (this.aggregateType){
				case -1: 
					sd = encryptor.encrypt_simple(i+ts, 0, 0, price+i+1, volume+i);
					sd1 = encryptor.encrypt_simple(i+ts, 1, 0, price+i+2, volume+i);
					break;
				case 1:
					sd = encryptor.encrypt_Aggregate1(i+ts, 0, 0, price+i+1, volume+i);
					//sd1 = encryptor.encrypt_Aggregate1(i+ts, 1, price+i+2, volume+i);
					break;
				case 2:
					sd = encryptor.encrypt_Aggregate2(i+ts, 0, 0, price+i+1, volume+i);
					sd1 = encryptor.encrypt_Aggregate2(i+ts, 1, 0, price+i+2, volume+i);
					break;
				case 3:
					sd = encryptor.encrypt_Aggregate3(i+ts, 0, 0, price+i+1, volume+i);
					//sd1 = encryptor.encrypt_Aggregate3(i+ts, 1, price+i+2, volume+i);
					break;
			}				
			encryptor.encrypt_join_price(sd, price+i+1);
			encryptor.encrypt_join_volume(sd, volume+i);
			//encryptor.encrypt_join_price(sd1, price+i+2);
			//encryptor.encrypt_join_volume(sd1, volume+i);
			epService.getEPRuntime().sendEvent(sd);
			//qepService.getEPRuntime().sendEvent(sd1);
		}				
	}
}
